#include "Crypto_Test.h"

void byte_fm_str(u8* b, const char* s) {
    static const u8 table[] = {
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
            0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    u64 slen = strlen(s);
    for (int i = 0; i < slen; i += 2)
        b[i >> 1] = table[s[i]] << 4 | table[s[i + 1]];
}

void Crypto_START() {
	printf("Init Crypto Module........\r\n");
    P2CONST(Csm_ConfigType, AUTOMATIC, CSM_APPL_DATA) configPtr1;
    P2CONST(CryIf_ConfigType, AUTOMATIC, CRYIF_APPL_DATA) configPtr2;
    P2CONST(Crypto_ConfigType, AUTOMATIC, CRYPTO_APPL_DATA) configPtr3;
    Csm_Init(configPtr1);
    CryIf_Init(configPtr2);
    Crypto_Init(configPtr3);
}

void Crypto_SM3_TEST() {
    const uint8 testInput[] = "abc";
    uint32 testInputLength = (sizeof(testInput) - 1);
    uint8 signaturePtr[32];
    uint32 signatureLengthPtr = 32;

    Std_ReturnType ret = Csm_Hash(
            CsmJob_SM3,
            CRYPTO_OPERATIONMODE_SINGLECALL,
            testInput,
            testInputLength,
            signaturePtr,
            &signatureLengthPtr
            );
    if (ret == E_OK) {
        printf("SM3 success\n");
        printf("Hash Value: ");
        for (int i = 0; i < 32; i++) {
            printf("%02x", signaturePtr[i]);
        }
        printf("\r\n");
    } else {
        printf("SM3 fail\n");
    }
}

void Crypto_SM2_SIGNVERIFY_TEST() {
	uint8 sig[72];
    uint32 siglen=0;

    const uint8 msgstr[] = "7C93AA2CB289D3639453CE12408F81295333528D0481163C76C92C2ED5A28F4846E63BC46A17AD1F894D48F71ADD661C00529B961C6D86E7B4B0E60246F0D814100762ACA15F89C78126C54AC7CBF742391B65C70C9D827EB99C33AE14F6D2660A80D3CDB372D142D4C9FD158D7722F81C7441213AF3159C53417D10692FD6043A792CA66CBD014AE0CEC76918F774F4EBA750D68F88D5413D54AE08C9B1A8F7D7A61B9C59E163A14D9BF99F472013C2E6E2E76FD885B682B135D90F2F4945E99489AA807FDD8D24745B2623C253BF55C3DE6A91A612A5979090EF7D804D0451EA5A2B1F23A3E97204246FB3FEFECBF1BCEFA42F447DA263289C84856A3ED5DCBEBBEA1C9FF986C0B44508EB8B04309F7228A8BE63D3212DAA17C7E8E2EE7644C5F31B7ACD7AF4E98C03BAB754B7CC742641BBA73E397D3B828B1CA20C749727BD3BDC45ACEEC18B82D476AA27ED36A61295AD914E0A69ED24726FDF2DF63A1D7EA8997558CA9DD9C44E15F1F40B5061A29FA7E43BD87F47069D420675C84B8CA5037C20BA1759CC3F8224392B3BF586BB429A38830CB8191550312ADBBF12B18F537D3FC5F40EF6F4D72A2F4245AE3F30F2654EB4C5C68F527612D976D901B7BD8AEB5E8E9071B91C22A3039531A3BCE0FF1D8DF55542AF9D2D147552E5771C3879E4407B0E86FD3012BDFA725E3BDD4233F8EA2A914D0006DC93D832DE11C7060EB2D9F90CAE502672EF8EAC2A31BD3B3594230CAA92DB6D0066FFA6C2A8E20EF56E2695EE5BC017D18A4F00A68F4C260BD672E2C5B8DF4CBB70C64A5E03032E50AB9E997A0F1FB0C498328EA6E7856A3FFBBA5F467745DBE1460EA785C61B4B07FE39E661A5B8F62C145E534EFF7D06CC343A6D49DF0CB2057D41897C024A1FBCA4857553ED498DEACF1923F0A2A8155FAB0AC5CB2C7837170E0871DF4895C1D0032DF7881F0C5F2BD493223F73BA21465FE34344FF705C88F5A7CE9D997E21CD365D21BB59F5B6B8A89C49EE7A8C68A93F43CDC69CF7A9BC61EB3225648E5B4D90AB136D8259D3B0606FC0B48F6ACC0FE232323F21D137E8C906BE5FDCC73401C2234CC4955ED9EA3D1906605DAC788EFF8A8649E8CE0B887E58164DB6FF5C23A95177E62D504D6C158A3F39F40587A317FDD63E1DC698222CA1CF5901B9F8BFE2E5B373DD2EBCCCA7FD8C1D58B9DF5B7DBEC250098144DCC759563FCA64674D75A6524F6F7E8DAD5870953C6DD11E0FD73680C837908FF07A95D891C151D8F4F5C84C26ECD672D2E5B390E335CBF25855C23B15BC3448BD916EF21528A457C3795F985AF1867685096504C87B60E7574E04A6E0E546588F471E3B77B2D4690030298D67FDEA7C52CE2FEC54AEFB4FFB5981AB44CCD196C2E0192053FC6A01EB372E61FBA5EAE26A4F2E32D295DADF189FEDD14A1F03C568B3D12C09E927";
    uint32 msglen = strlen(msgstr) >> 1;
    uint8 msg[msglen];
    bytes_from_hexstr(msg,msgstr,msglen);

    uint8 input_prikey[32];
    bytes_from_hexstr(input_prikey,"59A408B5ED69E2EBE8DC3DD4621453DA8B0DEBF294190ACD9CDB452E90B7763D",32);

//    byt_fm_str(input_pubkey_x, "2EB5019334A21AE618570009491C50B3C17D6E6B6B9CDEAF7E924B5004852252");
//    byt_fm_str(input_pubkey_y, "CE93DF59CFB607B4ED46A654341F4636C12333C3FA13E28F5B7404A30C0AFA84");

    Csm_KeyElementSet(0,1,input_prikey,sizeof(input_prikey));
    Csm_KeySetValid(0);

    Std_ReturnType ret = Csm_SignatureGenerate(
            CsmJob_SM2_SIGN,
            CRYPTO_OPERATIONMODE_SINGLECALL,
            msg,
            msglen,
            sig,
            &siglen
            );

	if (ret == E_OK) {
		printf("\n*****SM2SIGN success*****\r\n");
		printf("Sig Value: ");
		for (int i = 0; i < siglen; i++) {
			printf("%02x", sig[i]);
		}
		printf("\r\n");
	} else {
		printf("\n*****SM2SIGN fail*****\r\n");
	}


    Crypto_VerifyResultType result;
    uint8 input_pubkey[64];
    bytes_from_hexstr(input_pubkey,"2EB5019334A21AE618570009491C50B3C17D6E6B6B9CDEAF7E924B5004852252C"
    		"E93DF59CFB607B4ED46A654341F4636C12333C3FA13E28F5B7404A30C0AFA84",64);
    Csm_KeyElementSet(0,2,input_pubkey,sizeof(input_pubkey));
    Csm_KeySetValid(0);

    ret = Csm_SignatureVerify(
		CsmJob_SM2_VERIFY,
		CRYPTO_OPERATIONMODE_SINGLECALL,
		msg,
		msglen,
		sig,
		siglen,
		&result
		);

	if (ret == E_OK && result==1) {
		printf("\n*****SM2VERIFY success*****\r\n");
	} else {
		printf("\n*****SM2VERIFY fail*****\r\n");
	}
}

void Crypto_SM2ENC_TEST() {
	uint8 plain_str[] = "966397a223d8521deec7a9c256ba70b53e313fb056e962a35738561eb5b8f4cc322c2433c9ddbcc1b3d13a44a979808db5afc6b43bf43e90fca3ce9f294fce82";
	uint32 plainlen = strlen(plain_str) >> 1;
	uint8 plain[plainlen];
	bytes_from_hexstr(plain, plain_str, plainlen);

    uint8 cipher[plainlen+150];
    uint32 cipherlen = 0;

    uint8 input_pubkey[64];
    bytes_from_hexstr(input_pubkey,"2EB5019334A21AE618570009491C50B3C17D6E6B6B9CDEAF7E924B5004852252C"
    		"E93DF59CFB607B4ED46A654341F4636C12333C3FA13E28F5B7404A30C0AFA84",64);
    Csm_KeyElementSet(0,2,input_pubkey,sizeof(input_pubkey));
    Csm_KeySetValid(0);

    Std_ReturnType ret = Csm_Encrypt(CsmJob_SM2_ENC,
		CRYPTO_OPERATIONMODE_SINGLECALL,
		plain,
		plainlen,
		cipher,
		&cipherlen
		);

	if (ret == E_OK) {
		printf("\n*****SM2ENC success*****\r\n");
		printf("Ciphertext Value: ");
		for (int i = 0; i < cipherlen; i++) {
			printf("%02x", cipher[i]);
		}
		printf("\r\n");
	} else {
		printf("\n*****SM2ENC fail*****\r\n");
	}
}

void Crypto_SM2DEC_TEST() {
	const uint8 cipher_str[] = "3081a9022004ebfc718e8d1798620432268e77feb6415e2ede0e073c0f4f640ecd2e149a73022100e858f9d81e5430a57b36daab8f950a3c64e6ee6a63094d99283aff767e124df0042058e2bae5ee0538b0e63cf80595494604e87d32dc03f8b69f48eebe7702994dca0440fdd56238a9d164090604b7b658bcf02935b7a3d21497a1faafccf03f133e76e45f098831580410e208c3a547fbeeb2a78f4824b6d9b67b36da90ebf06b637eb5";
	uint32 cipherlen = strlen(cipher_str) >> 1;
	uint8 cipher[cipherlen];
    bytes_from_hexstr(cipher, cipher_str, cipherlen);

	uint8 plain[cipherlen-97];
	uint32 plainlen = 0;

    uint8 input_prikey[32];
    bytes_from_hexstr(input_prikey,"59A408B5ED69E2EBE8DC3DD4621453DA8B0DEBF294190ACD9CDB452E90B7763D",32);

    Csm_KeyElementSet(0,1,input_prikey,sizeof(input_prikey));
    Csm_KeySetValid(0);

    Std_ReturnType ret = Csm_Decrypt(CsmJob_SM2_DEC,
			CRYPTO_OPERATIONMODE_SINGLECALL,
			cipher,
			cipherlen,
			plain,
			&plainlen
			);

	if (ret == E_OK) {
		printf("\n*****SM2DEC success*****\r\n");
		printf("Msg Value: ");
		for (int i = 0; i < plainlen; i++) {
			printf("%02x", plain[i]);
		}
		printf("\r\n");
	} else {
		printf("\n*****SM2DEC fail*****\r\n");
	}
}
